package blockchain

import (
	"bufio"
	"encoding/binary"
	"log"
	"os"
	"time"
)

const (
	// FILENAME - 区块文件名
	FILENAME = "./block/blockchain.dat"
)

// Persistence - 持久化类
type Persistence struct {
}

func (p *Persistence) getF() *os.File {
	var filename = FILENAME
	var f *os.File
	var err1 error
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		//如果文件存在
		f, err1 = os.Create(filename)
		if err1 != nil {
			log.Println(err1)
		}
	} else {
		f, err1 = os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, os.ModeAppend)
		if err1 != nil {
			log.Println(err1)
		}
	}
	fi, err := f.Stat()
	if err != nil {
		log.Println(err)
	}
	if int(fi.Size()) >= Config.FileSize {
		os.Rename("./block/blockchain.dat", "./block/blockchain.dat."+time.Now().String())
		f, err1 = os.Create(filename)
		if err1 != nil {
			log.Println(err1)
		}
	}
	return f
}

// Save - 持久化区块
func (p *Persistence) Save(blocks ...[]byte) {
	f := p.getF()
	defer f.Close()
	for _, data := range blocks {
		len := uint32(len(data))
		w := bufio.NewWriter(f)
		// 先写入block长度
		binary.Write(w, binary.BigEndian, len)
		// 写入block数据
		w.Write(data)
		w.Flush()
	}
}

// Load - 加载某一文件区块
func (p *Persistence) Load(filename string) (result [][]byte, err error) {
	var f *os.File
	f, err = os.OpenFile(filename, os.O_RDWR, os.ModeAppend)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	r := bufio.NewReader(f)
	var len1 uint32
	for {
		// 先读取block长度
		if err := binary.Read(r, binary.BigEndian, &len1); err != nil {
			break
		}
		// 读取block数据
		data := make([]byte, len1)
		if _, err := r.Read(data); err != nil {
			break
		} else {
			result = append(result, data)
		}
	}
	return result, nil
}

// generateDB - 根据区块数据，生成交易数据库
func (p *Persistence) generateDB() {
	// todo:
}
